﻿#region

using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

#endregion

namespace BuildMotion.MotionTracker.Service.Common
{
    public class CyclicReferencesAwareContractBehavior : IContractBehavior
    {
        private const bool ignoreExtensionDataObject = false;
        private const Int32 maxItemsInObjectGraph = 0xFFFF;

        private readonly bool isOn;

        public CyclicReferencesAwareContractBehavior(bool isOn)
        {
            this.isOn = isOn;
        }

        #region IContractBehavior Members

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            ReplaceDataContractSerializerOperationBehaviors(contractDescription, isOn);
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
            ReplaceDataContractSerializerOperationBehaviors(contractDescription, isOn);
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
        }

        #endregion

        internal static void ReplaceDataContractSerializerOperationBehaviors(ContractDescription contractDescription, bool isOn)
        {
            foreach (var operation in contractDescription.Operations)
            {
                ReplaceDataContractSerializerOperationBehavior(operation, isOn);
            }
        }

        internal static void ReplaceDataContractSerializerOperationBehavior(OperationDescription operation, bool isOn)
        {
            if (operation.Behaviors.Remove(typeof (DataContractSerializerOperationBehavior)) || operation.Behaviors.Remove(typeof (ApplyCyclicDataContractSerializerOperationBehavior)))
            {
                operation.Behaviors.Add(new ApplyCyclicDataContractSerializerOperationBehavior(operation, maxItemsInObjectGraph, ignoreExtensionDataObject, isOn));
            }
        }
    }
}